/*
 * Copyright (c) 2007 T.Cogghe, D.Leroux, S.Lévignac, S.Rives
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
#ifndef __IMAGE_H__
#define __IMAGE_H__

#include "config.h"
#include <gtkmm/image.h>
#include <gdkmm/pixbuf.h>
#include <math.h>
#include <iostream>
using namespace std;

#include "types.hh"

class Forme;

class Image {
	protected:
		Glib::RefPtr<Gdk::Pixbuf>  _pixbuf;
		unsigned char*px;	/* pixels */
		int p;			/* pitch */
		int w;			/* width */
		int h;			/* height */
		int pxsz;		/* pixel size (in bytes) */
		int nchan;		/* n channels */

	private:
		//PointsCle _pclef;
		Forme*f;

		void _init(Glib::RefPtr<Gdk::Pixbuf> gpb);

	public:
		static const unsigned char black[4];

		/* Dark : wrapper pour des objets image */
		class Dark {
		private:
			int k;
			unsigned char tint[4];
			const Image*pic;
		public:
			static Image* imgNoir;	// un seul fond noir pour toutes les images
			static double absorption;			// toutes les images doivent avoir à peu près les mêmes qualités, la quantité de pixels absorbés reste la même pour toutes
			typedef enum { Aucun, PicFreq, QteAbs, ImgNoir } Algo;
			typedef enum { Gate, Sub } Mode;
			static Algo algo;
			static Mode mode;

			Dark(const Image*pic);
			const unsigned char*operator()(const int x,const int y);
			int largeur() const { return pic->largeur(); }
			int hauteur() const { return pic->hauteur(); }
		};

		/* Seuil : détermine le seuil de luminosité des astres */
		class Seuil {
			/* tente de déterminer le niveau autour duquel le contraste est le plus élevé */
		private:
			int k;
		public:
			Seuil(const Image*pic);
			operator int() { return k; }
		};

		/* Seuil_defunct : détermine le seuil de luminosité des astres ALGORITHME FOIREUX SUR LES GRANDES IMAGES */
		class Seuil_defunct {
			/* tente de déterminer le niveau autour duquel le contraste est le plus élevé */
		private:
			int k;
			double ctrst(const Image*i,const int x,const int y);

			Position& pixACote(const Image*i,const int x,const int y);


		public:
			Seuil_defunct(const Image*pic);
			operator int() { return k; }
		};


		Image(Gtk::Image*i)  { _init(i->get_pixbuf()); }
		Image(Glib::RefPtr<Gtk::Image> i) { _init(i->get_pixbuf()); }
		Image(Glib::RefPtr<Gdk::Pixbuf> p) { _init(p); }
		Image(std::string filename) { _init(Gdk::Pixbuf::create_from_file(filename)); }
		virtual ~Image() {}

		virtual unsigned char* operator() (int x, int y) const;
		static double lumd(unsigned char*pix);
		static int lum(unsigned char*pix);
		static unsigned char ajoutSat(unsigned char a,unsigned char b);
		int pixInf(int x,int y,int seuil) const;

		int pixSup(int x,int y,int seuil) const;

		operator Glib::RefPtr<Gdk::Pixbuf>() const { return _pixbuf; }
		Glib::RefPtr<Gdk::Pixbuf> operator *() const { return _pixbuf; }
		Glib::RefPtr<Gdk::Pixbuf> copiePixbuf() const { return _pixbuf->copy(); }

		int largeur() const { return w; }
		int hauteur() const { return h; }

		Image& operator += (Image&a);

		//PointsCle& pointsCle() { return _pclef; }
		Forme* forme() const { return f; }
		Forme*& forme() { return f; }
};


#endif
